package com.tanhua.server.service;


import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.commons.templates.SmsTemplate;
import com.tanhua.domain.db.*;
import com.tanhua.domain.vo.*;
import com.tanhua.dubbo.api.*;
import com.tanhua.server.interceptor.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SettingsService {

    //注入配置文件中属性
    @Value("${tanhua.redisValidateCodeKeyPrefix}")
    private String redisValidateCodeKeyPrefix;

    //注入-远程调用 SettingsApi 我的--通用设置
    @Reference
    private SettingsApi settingsApi;

    //注入-远程调用 QuestionApi 我的--通用设置--陌生人问题
    @Reference
    private QuestionApi questionApi;

    //注入-远程调用 blackListApi  我的--通用设置--黑名单
    @Reference
    private BlackListApi blackListApi;

    //注入-远程调用 UserInfoApi  我的--通用设置--黑名单人员信息
    @Reference
    private UserInfoApi userInfoApi;

    //注入 发送验证码模板
    @Autowired
    private SmsTemplate smsTemplate;

    //注入-- redis
    @Autowired
    private RedisTemplate redisTemplate;

    //注入UserApi
    @Reference
    private UserApi userApi;


    /**
     * 通用设置读取 当前用户的设置
     *
     * @return
     */
    public SettingsVo querySettins() {
        //构建vo
        SettingsVo vo = new SettingsVo();
        //获取登陆用户信息
        User loginUser = UserHolder.getUser();
        //通过登录用户id查询用户设置的陌生人问题
        Question question = questionApi.selectById(loginUser.getId());

        //这里定义系统默认的问题
        vo.setStrangerQuestion("你喜欢我嘛？");
        //设置陌生人问题
        if (null != question) {
            //设置陌生人问题
            vo.setStrangerQuestion(question.getTxt());
        }
        // 查询登陆用户的通知设置
        Settings settings = settingsApi.findById(loginUser.getId());
        // 设置到vo里
        if (settings != null) {
            BeanUtils.copyProperties(settings, vo);
        }
        //设置用户的手机号码和id
        vo.setId(UserHolder.getUserId());
        vo.setPhone(UserHolder.getUser().getMobile());
        //返回到controller
        return vo;
    }

    /**
     * 通用设置--保存
     *
     * @return
     */
    public void updateNotification(SettingsVo vo) {

        //vo转成pojo
        Settings settings = new Settings();
        BeanUtils.copyProperties(vo, settings);
        //设置操作的用户id为登录用户的id
        settings.setUserId(UserHolder.getUserId());

        settingsApi.save(settings);
    }

    /**
     * 通用设置--黑名单--分页查询
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult<UserInfoVoAge> blackList_2(Long page, Long pagesize) {
        //1.调用api通过登录用户id，然后分页查询登录用户的黑名单列表
        PageResult pageResult = blackListApi.findPageByUserId(UserHolder.getUserId(), page, pagesize);

        //2.获取分页结果集
        List<BlackList> blackLists = pageResult.getItems();

        //3.补全黑名单人员的用户详情
        //isEmpty：非空判断 null--true

        if (!CollectionUtils.isEmpty(blackLists)) {   //不为空--有黑名单

            List<UserInfoVoAge> voList = new ArrayList<>(blackLists.size()); //初始化一个集合
            //批量查询黑名单人员详情
            for (BlackList blackList : blackLists) { //遍历黑名单人员 取出黑名单人员的id
                Long blackUserId = blackList.getBlackUserId();

                //查询这个黑名单人员的信息
                UserInfo blackUserInfo = userInfoApi.findById(blackUserId);

                //转成vo
                UserInfoVoAge voAge = new UserInfoVoAge();
                BeanUtils.copyProperties(blackUserInfo, voAge);
                voList.add(voAge);

            }
            //重置设置查询结果
            pageResult.setItems(voList);

        }
        //返回
        return pageResult;

    }

    /**
     * 通用设置--黑名单--分页查询
     * 使用stream流 1.0
     *
     * @param page
     * @param pagesize
     * @return
     */
    public PageResult<UserInfoVoAge> blackList(Long page, Long pagesize) {

        //1.调用api通过登录id分页查询黑名单列表
        PageResult pageResult = blackListApi.findPageByUserId(UserHolder.getUserId(), page, pagesize);

        //2.获取分页结果集--里面有黑名单用户的id
        List<BlackList> blackLists = pageResult.getItems();
        //3.补全黑名单人员的用户详情--（这里存在这个用户没有黑名单的情况所以做非空判断）
        if (!CollectionUtils.isEmpty(blackLists)) { //空则true  这里取反不是空则为true
            //3.1批量查询黑名单人员的信息--（根据id）
            List<UserInfoVoAge> userInfoVoList = new ArrayList<>(); //返回数据需要用vo

            //3.2获取所有黑名单人员的id
            List<Long> BlackUserIds = blackLists.stream().map(BlackList::getBlackUserId).collect(Collectors.toList());

            //3.3根据黑名单id查询出黑名单用户的集合信息
            List<UserInfo> userInfoList = userInfoApi.findByBatchId(BlackUserIds);

            //3.4遍历黑名单人员的id 取出id
            for (BlackList blackList : blackLists) {

                Long blackUserId = blackList.getBlackUserId(); //黑名单人员的id
                //3.5查询这个黑名单人员的详细信息
                UserInfo blackUserInfo = getUserInfo(blackUserId,userInfoList);
                //3.6转成vo
               UserInfoVoAge vo = new UserInfoVoAge();
               BeanUtils.copyProperties(blackUserInfo,vo);
                userInfoVoList.add(vo);
            }

            //3.7重置查询结果 -- （更新pageResult里面的数据）
            pageResult.setItems(userInfoVoList);


        }
        //4返回
        return pageResult;


    }

    /**
     * 通过黑名单用户的id集合中找出黑名单用户的信息
     * @param blackUserId   黑名单表中的user_Id
     * @param userInfoList userInfo表中的id
     * @return
     */
    private UserInfo getUserInfo(Long blackUserId, List<UserInfo> userInfoList) {
        for (UserInfo userInfo : userInfoList) {
            if(userInfo.getId().equals(blackUserId)){
                return userInfo;
            }
        }
        return null;
    }

    /**
     * 通用设置--移除黑名单
     *
     * @param blackUserId
     */
    public ResponseEntity removeBlackList(Long blackUserId) {
        //获取登录用户id
        Long loginUserID = UserHolder.getUserId();

        //调用api删除
        blackListApi.delete(blackUserId, loginUserID);
        return ResponseEntity.ok(null);
    }

    /**
     * 通用设置--保存陌生人问题信息
     *
     * @param content
     */
    public void updateQuestion(Map<String, String> content) {

        //1. 构建pojo
        Question question = new Question();
        question.setTxt(content.get("content"));
        question.setUserId(UserHolder.getUserId());
        //2. 调用api保存
        questionApi.save(question);


    }

    /**
     * 通用设置--发送验证码
     * TODO 为什么这里不用之前设置的redis前缀 而要自己创建一个实体类
     */
    public void sendValidateCode() {
//1.通过手机号来获取redis中的验证码
        String key = redisValidateCodeKeyPrefix + UserHolder.getUser().getMobile();
        String codeInRedis = (String) redisTemplate.opsForValue().get((key));
        //2.redis中有值，则报错:验证码没有过期
        if (codeInRedis != null) {
            throw new TanHuaException(ErrorResult.duplicate());
        }
        //TODO
        //3.redis中没有值，生成验证码
        //这是一个java自带的工具类 RandomStringUtils
        String validateCode = "123456";/*RandomStringUtils.randomNumeric(6);
        //4调用smsTemplate发送验证码
        Map<String, String> sendResult = smsTemplate.sendValidateCode(phone, validateCode);
        //5.发送验证码返回的信息不能为空
        if (sendResult != null) {
            throw new TanHuaException(ErrorResult.fail());
        }*/
        //用占位符看看日志里面是否成功，验证码 和 手机号 是否多少
        log.info("发送验证码成功。${},${}", validateCode, key);
        //5.存入redis中 有效期十分钟
        redisTemplate.opsForValue().set(key, validateCode, 10, TimeUnit.MINUTES);
    }

    /**
     * 通用设置--校验验证码
     *
     * @param verificationCode
     * @return
     */
    public Boolean checkValidateCode(String verificationCode) {
        //取出存在redis中的key
        String redisKey = redisValidateCodeKeyPrefix + UserHolder.getUser().getMobile();

        //redis中的验证码
        String redisValue = (String) redisTemplate.opsForValue().get(redisKey);

        redisTemplate.delete(redisKey);//防止重复提交
        log.debug("==========修改手机号 校验 验证码:{},{},{}", UserHolder.getUser().getMobile(), redisValue, verificationCode);

        //StringUtils.isEmpty 非空判断 空--true
        if (StringUtils.isEmpty(redisValue)) {
            throw new TanHuaException(ErrorResult.loginError());
        }

        //返回结果
        return redisValue.equals(verificationCode);
    }

    /**
     * 通用设置--修改手机号--保存手机号并删除token让用户重新
     *
     * @param phone
     * @param token
     */
    public void changeMobile(String phone, String token) {


        userApi.updateMobile(UserHolder.getUserId(), phone);

        //删除token
        String TokenKey = "TOKEN_" + token;
        redisTemplate.delete(TokenKey);


    }
}
